
/*
 * Todos:
 * element update
 * origami object creation
 * origami object update
 * sending delta on client update
 * delta doesn't contain functions, sync - toJSON?
 * 
 */

// --------------------
// -- TEST FUNCTIONS --
// --------------------
if(!tests.scenarios) {
    tests.scenarios = {};
}
tests.scenarios.Theory = {
    name: "Theory"
};

tests.scenarios.Theory.StateUpdateInitializesCounter = function(){
    // given
    var testNumber = 15;
    var id = "testUser"+testNumber;
    var state = {};
    state[id] = {
        id: id,
        text: "text"
    };
    mindgraph.idCount = testNumber - 2;
    
    // when
    mindgraph.theory.stateHandler(state);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(mindgraph.idCount === testNumber);
    resultObject.resultMessage = "IdCount: " + mindgraph.idCount;
    
    return resultObject;
}

tests.scenarios.Theory.ModelCanCreateNewNodeWithNewId = function(){
    // given
    var type = mindgraph.theory.types.node;
    var setup = {
        text: "testtext",
        type: type
    };
    var testCount = 7;
    mindgraph.idCount = testCount;
    
    // when
    var newNode = mindgraph.theory.Model.create(setup);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(newNode != undefined);
    assert(newNode.type === type);
    assert(newNode.text === setup.text);
    assert(newNode.id === mindgraph.getParticipantName() + testCount);
    resultObject.setResultMessage(newNode);

    return resultObject;
}

tests.scenarios.Theory.ModelCanCreateNewEdgeWithNewId = function(){
    // given
    var type = mindgraph.theory.types.edge;
    var setup = {
        text: "testedge",
        type: type
    };
    var testCount = 11;
    mindgraph.idCount = testCount;
    
    // when
    var newEdge = mindgraph.theory.Model.create(setup);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(newEdge !== undefined);
    assert(newEdge.type === type);
    assert(newEdge.text === setup.text);
    assert( newEdge.id === mindgraph.getParticipantName() + testCount);
    resultObject.setResultMessage(newEdge);

    return resultObject;
}

tests.scenarios.Theory.ModelCreateHandlesWrongElementTypes = function(){
    // given
    var type = "unknownType"
    var caught = undefined;
    
    // when
    try {
        mindgraph.theory.Model.create({
            type: type
        });
    } 
    catch (e) {
        caught = e;
    }
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(caught !== undefined);
    
    resultObject.setResultMessage("Caught: " + (caught && caught.message));
    return resultObject;

}

tests.scenarios.Theory.ModelCanCreateNodeWithSetId = function(){
    // given
    var testCount = 7;
    var type = mindgraph.theory.types.node;
    var setup = {
        text: "testtext",
        id: mindgraph.getParticipantName() + testCount,
        type: type
    };
    mindgraph.theory.Model.remove(setup.id);
    mindgraph.idCount = testCount + 8;
    
    // when
    var newNode = mindgraph.theory.Model.create(setup);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(newNode != undefined);
    assert(newNode.type === type);
    assert(newNode.text === setup.text);
    assert(newNode.id === mindgraph.getParticipantName() + testCount);
    resultObject.setResultMessage(newNode);
    return resultObject;
}

tests.scenarios.Theory.ModelCanCreateEdgeWithSetId = function(){
    // given
    var testCount = 11;
    var type = mindgraph.theory.types.edge;
    var setup = {
        text: "testedge",
        id: mindgraph.getParticipantName() + testCount,
        type: type
    };
    mindgraph.theory.Model.remove(setup.id);
    mindgraph.idCount = testCount - 4;
    
    // when
    var newEdge = mindgraph.theory.Model.create(setup);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(newEdge != undefined);
    assert(newEdge.type === type);
    assert(newEdge.text === setup.text);
    assert(newEdge.id === mindgraph.getParticipantName() + testCount);
    resultObject.setResultMessage(newEdge);
    return resultObject;
}

tests.scenarios.Theory.ModelCanFindExistingElement = function(){
    // given
    var testCount = 11;
    var type = mindgraph.theory.types.edge;
    var setup = {
        text: "testedge",
        id: mindgraph.getParticipantName() + testCount,
        type: type
    };
    var newEdge = mindgraph.theory.Model.createOrFind(setup);
    
    // when
    var existingEdge = mindgraph.theory.Model.find(setup.id);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(existingEdge != undefined);
    assert(existingEdge === newEdge);
    resultObject.setResultMessage(existingEdge);
    return resultObject;
}

tests.scenarios.Theory.CreateOrFindCanFindExistingElement = function(){
    // given
    var testCount = 26;
    var type = mindgraph.theory.types.edge;
    var setup = {
        text: "testedge",
        id: mindgraph.getParticipantName() + testCount,
        type: type
    };
    var newEdge = mindgraph.theory.Model.create(setup);
    
    // when
    var existingEdge = mindgraph.theory.Model.createOrFind(setup);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(existingEdge != undefined);
    assert(existingEdge === newEdge);
    resultObject.setResultMessage(existingEdge);
    return resultObject;
}

tests.scenarios.Theory.CreateOrFindCanCreateNewElement = function(){
    // given
    var testCount = 17;
    var type = mindgraph.theory.types.edge;
    var setup = {
        type: type,
        text: "testedge",
        id: mindgraph.getParticipantName() + testCount
    };
    var existingEdge = mindgraph.theory.Model.find(setup.id);
    
    // when
    var newEdge = mindgraph.theory.Model.createOrFind(setup);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(newEdge != undefined);
    assert(existingEdge == undefined);
    assert(newEdge.id === setup.id);
    assert(newEdge.text === setup.text);
    assert(newEdge.type === type);
    resultObject.setResultMessage(newEdge);
    return resultObject;
}

tests.scenarios.Theory.ModelCanDeleteElement = function(){
    // given
    var testCount = 26;
    var type = mindgraph.theory.types.edge;
    var setup = {
        text: "testedge",
        id: mindgraph.getParticipantName() + testCount,
        type: type
    };
    mindgraph.theory.Model.createOrFind(setup);
    
    // when
    var res = mindgraph.theory.Model.remove(setup.id);
    
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    var existingEdge = mindgraph.theory.Model.find(setup.id);
    assert(res === true);
    assert(existingEdge === undefined);
    resultObject.setResultMessage("Delete result: " + res);
    return resultObject;
}

tests.scenarios.Theory.StateUpdateCreatesNewElement = function () {
    // given
    //var state = createState("userish", 42);
    var id = "userish42";
    var state = {};
    state[id] = {
        id: id,
        text: "text"
    };
    mindgraph.theory.Model.remove(id);
    
    // when
    mindgraph.theory.stateHandler(state);
	
    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    //var keys = state.getKeys();
    var resultMessage = "Keys: ";
    for(var key in state) {
        var existingElement = mindgraph.theory.Model.find(key);
        assert(existingElement !== undefined);
        resultMessage += state[key] + ", ";
    }
    resultObject.setResultMessage(resultMessage);
    return resultObject;
}

tests.scenarios.Theory.StateUpdateRemovesDeletedElement = function () {
    // given
    var testString1 = "toast31";
    var testString2 = "toast34";
    var state = {};
    state[testString1] = {
        id: testString1,
        text: "someTxt1"
    };
    state[testString2] = {
        id: testString2,
        text: "someTxt2"
    };
    mindgraph.theory.stateHandler(state);
    var existingElement = mindgraph.theory.Model.find(testString2);

    // when
    delete state[testString2];
    mindgraph.theory.stateHandler(state);

    // then
    var deletedElement = mindgraph.theory.Model.find(testString2);
    
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(existingElement !== undefined);
    assert(deletedElement === undefined);

    resultObject.setResultMessage(deletedElement);
    return resultObject;
}

tests.scenarios.Theory.StateUpdateTriggersUpdateAll = function () {
    // given
    var oldUpdateAll = mindgraph.theory.updateAll;
    var updateCount = 0;
    var callingArguments = undefined;
    mindgraph.theory.updateAll = function() {
        updateCount++;
        callingArguments = arguments;
    }
    var state = createState("userish", 42);

    // when
    mindgraph.theory.stateHandler(state);

    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(updateCount === 1);
    assert(callingArguments.length === 0);

    resultObject.setResultMessage(callingArguments);
    mindgraph.theory.updateAll = oldUpdateAll;

    return resultObject;
}

tests.scenarios.Theory.StateUpdateCallsDataUpdateOnElement = function () {
    // given
    var username = "userush";
    var count = 36;
    var id = username+count;
    var args = undefined;
    var callCount = 0;


    mindgraph.theory.Model.remove(id);
    var existingElement = mindgraph.theory.Model.create({
        id: id,
        text: "someText",
        type: "node"
    });

    var oldDataUpdate = existingElement.dataUpdate;
    existingElement.dataUpdate = function() {
        args = arguments;
        callCount++;
    }

    var state = {};
    state[id] = JSON.stringify({
        id: id,
        text: "someOtherText"
    });

    // when
    mindgraph.theory.stateHandler(state);

    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    existingElement = mindgraph.theory.Model.find(id);
    assert(args !== undefined);
    assert(callCount === 1);
    resultObject.setResultMessage(existingElement);
    existingElement.dataUpdate = oldDataUpdate;
    return resultObject;
}

tests.scenarios.Theory.StateUpdateUpdatesExistingElement = function () {
    // given
    var username = "amino";
    var count = 19;
    var id = username+count;
    var otherText = "someOtherTestText";

    mindgraph.theory.Model.remove(id);
    var existingElement = mindgraph.theory.Model.create({
        id: id,
        text: "someTestText",
        type: "edge"
    });


    var state = {};
    state[id] = {
        id: id,
        text: otherText
    };

    // when
    mindgraph.theory.stateHandler(state);

    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    existingElement = mindgraph.theory.Model.find(id);
    assert(existingElement !== undefined);
    assert(existingElement.text === otherText);
    assert(existingElement.syncStatus === mindgraph.theory.SyncStatusType.serverUpdated);
    resultObject.setResultMessage(existingElement);
    return resultObject;
}

tests.scenarios.Theory.ModelsRemoveAllRemovesAllElements = function () {
    // given
    var id1="userid2";
    var id2="userid5";

    var state = {};
    state[id1] = {
        id: id1,
        text: "otherText1"
    };
    state[id2] = {
        id: id2,
        text: "otherText2"
    };
    mindgraph.theory.stateHandler(state);

    // when
    mindgraph.theory.Model.removeAll();

    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    var count = 0;
    for(var key in mindgraph.theory.Model.elements) {
        count++;
    }
    assert(count === 0);

    resultObject.setResultMessage("Count: "+count);
    return resultObject;
}

tests.scenarios.Theory.UpdateAllCallsUpdateOnAllElements = function () {
    // given
    mindgraph.theory.Model.removeAll();
    var count1 = 0;
    var count2 = 0;

    var state = {};
    var id1="userid2";
    var id2="userid5";
    state[id1] = {
        id: id1,
        text: "otherText1"
    };
    state[id2] = {
        id: id2,
        text: "otherText2"
    };
    mindgraph.theory.stateHandler(state);
    var element1 = mindgraph.theory.Model.find(id1);
    var element2 = mindgraph.theory.Model.find(id2);

    element1.update = function() {
        count1++;
    }

    element2.update = function() {
        count2++;
    }

    // when
    mindgraph.theory.updateAll();

    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(element1 !== undefined);
    assert(element2 !== undefined);
    assert(count1 === 1);
    assert(count2 === 1);

    resultObject.setResultMessage("Updates was called ["+count1+", "+count2+"] times.");
    return resultObject;
}

tests.scenarios.Theory.NewElementUpdateCallsOrigamiCreate = function () {
    // given
    var newElement = mindgraph.theory.Model.create({
        id: "eleph14",
        text: "Simba",
        type: "node"
    });
    var oldCreate = mindgraph.origami.Model.create;
    var callCount = 0;
    var callArgs = undefined;
    mindgraph.origami.Model.create = function() {
        callCount++;
        callArgs = arguments;
    }

    // when
    newElement.update();

    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(callCount === 1);
    assert(callArgs !== undefined);
    assert(callArgs && callArgs.length === 0);
    resultObject.setResultMessage(callArgs);

    mindgraph.origami.Model.create = oldCreate;
    return resultObject;
}

tests.scenarios.Theory.NewElementUpdatePopulatesOrigamiObject = function () {
    var newElement = mindgraph.theory.Model.create({
        id: "eleph36",
        text: "Samba",
        type: "edge"
    });
    var oldCreate = mindgraph.origami.Model.create;
    var testObject = {
        id: "testObject",
        index: 14
    };
    mindgraph.origami.Model.create = function() {
        return testObject;
    }

    // when
    newElement.update();

    // then
    var resultObject = new tests.prv.ResultObject();
    var assert = resultObject.createAssert();

    assert(newElement.origamiObject !== undefined);
    assert(newElement.origamiObject === testObject);
    resultObject.setResultMessage(newElement.origamiObject);

    mindgraph.origami.Model.create = oldCreate;
    return resultObject;
}
// ---------------------------
// -- END of TEST FUNCTIONS --
// ---------------------------
